home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / mg / src.lzh / amiga / fileio.c < prev    next >
C/C++ Source or Header  |  1990-05-23  |  14KB  |  638 lines

  1. /*
  2.  * Name:    MG 2a401 Commodore Amiga file I/O. Last edit:    05-May-88
  3.  * swalton@solar.stanford.edu Next-to-Last edit:    16-Dec-87
  4.  * mic@emx.utexas.edu Created:    23-Jul-86 mic@emx.utexas.edu
  5.  * 
  6.  * Read and write ASCII files. All of the low level file I/O knowledge is here.
  7.  * Uses AmigaDOS standard I/O and does its own dynamic buffering; this seems
  8.  * to save about 2K worth of space in the executable image.
  9.  */
  10.  
  11. #undef        LATTICE
  12. #undef        MANX
  13. #include    "compiler.h"
  14. #include    "no_backup.h"
  15. #include    "no_startup.h"
  16. #include    "no_dir.h"
  17. #include    "no_dired.h"
  18.  
  19. #ifdef        LATTICE
  20. #include    <stdlib.h>
  21. #include    <string.h>
  22. #include    <exec/types.h>
  23. #endif
  24. #include    "use_arp.h"
  25. #include    "foob.h"
  26. #include    <exec/memory.h>
  27. #include    <libraries/dos.h>
  28. #include    <libraries/dosextens.h>
  29. #ifdef        USE_ARP
  30. #include    <arpfunctions.h>
  31. #include    <libraries/arpbase.h>
  32. #else
  33. #define FCHARS    32L
  34. #endif
  35.  
  36. #ifdef LATTICE
  37. #include <proto/all.h>
  38. #else
  39. #include    <functions.h>
  40. #endif
  41. #undef    TRUE
  42. #undef    FALSE
  43. #include    "def.h"
  44. #include    "line.h"
  45. #include    "buffer.h"
  46.  
  47. #ifdef ANSI
  48. #undef EOF
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #endif
  53.  
  54. #ifndef    NO_PROTO
  55. char           *mktemp PROTO((char *));
  56. #endif
  57.  
  58. #ifdef    LATTICE
  59. #undef LATTICE
  60. #include <dos.h>
  61. #define isdirectory(x)    (getfa(x) == 1)
  62. #endif
  63.  
  64.  
  65. #define    NIOBUF            4096
  66.  
  67. static VOID FlushBuf PROTO((VOID));
  68.  
  69. static BPTR     ffh = 0;
  70. static UBYTE   *iobuf;
  71. static int      ibufo, niobuf;
  72. static LONG     iostat, access_mode;
  73. #ifdef    MANX
  74. extern char    *strncpy(), *strncat(), *index(), *rindex();
  75. #endif
  76.  
  77. #ifdef    LATTICE
  78. static void     TackOn(char *path, char *file);
  79. #define    index    strchr
  80. #define rindex    strrchr
  81. #endif
  82.  
  83. #define    getch()        (ibufo == niobuf) ? FillBuf() : iobuf[ibufo++]
  84. #define putch(c)    {if (niobuf == NIOBUF) FlushBuf(); iobuf[niobuf++] = c;}
  85.  
  86. /*
  87.  * Open the Emacs internal file for reading.
  88.  */
  89. ffropen(fn)
  90.     char           *fn;
  91. {
  92.     if ((iobuf = AllocMem((ULONG) NIOBUF, 0L)) == NULL)
  93.         return (FIOERR);
  94.  
  95.     if ((ffh = Open(fn, access_mode = MODE_OLDFILE)) == 0L) {
  96.         FreeMem(iobuf, (ULONG) NIOBUF);
  97.         return (FIOFNF);
  98.     }
  99.     ibufo = niobuf = 0;
  100.     return (FIOSUC);
  101. }
  102.  
  103. /*
  104.  * Open a file for writing.  Return TRUE if all is well, and FALSE on error
  105.  * (cannot create).
  106.  */
  107.  
  108. ffwopen(fn)
  109.     char           *fn;
  110. {
  111.     if ((iobuf = AllocMem((ULONG) NIOBUF, 0L)) == NULL)
  112.         return (FIOERR);
  113.     if ((ffh = Open(fn, access_mode = MODE_NEWFILE)) == 0L) {
  114.         ewprintf("Cannot open file for writing");
  115.         FreeMem(iobuf, (ULONG) NIOBUF);
  116.         return (FIOERR);
  117.     }
  118.     niobuf = 0;
  119.     iostat = NIOBUF;    /* pretend we wrote out a full buffer last
  120.                  * time */
  121.     return (FIOSUC);
  122. }
  123.  
  124. /*
  125.  * Close a file, flushing the output buffer.  Should look at the status.
  126.  */
  127. ffclose()
  128. {
  129.     if (access_mode == MODE_NEWFILE)
  130.         FlushBuf();
  131.     if (ffh)
  132.         (void) Close(ffh);
  133.     if (iobuf)
  134.         FreeMem(iobuf, (ULONG) NIOBUF);
  135.     return (FIOSUC);
  136. }
  137.  
  138. /*
  139.  * Write a buffer to the already opened file. bp points to the buffer. Return
  140.  * the status. Check only at the newline and end of buffer.
  141.  */
  142. ffputbuf(bp)
  143.     struct buffer  *bp;
  144. {
  145.     register char  *cp;
  146.     register char  *cpend;
  147.     register struct line *lp;
  148.     register struct line *lpend;
  149.  
  150.     lpend = bp->b_linep;
  151.     lp = lforw(lpend);
  152.     do {
  153.         cp = <ext(lp)[0];    /* begining of line     */
  154.         cpend = &cp[llength(lp)];    /* end of line         */
  155.         while (cp != cpend)
  156.             putch(*(cp++));    /* putch only evalutes its arg once */
  157.         lp = lforw(lp);
  158.         if (lp == lpend)
  159.             break;    /* no implied newline on last line */
  160.         putch('\n');
  161.     } while (iostat > 0L);
  162.  
  163.     if (iostat == -1L) {
  164.         ewprintf("Write I/O error");
  165.         return FIOERR;
  166.     }
  167.     return FIOSUC;
  168. }
  169.  
  170. /*
  171.  * Read a line from a file, and store the bytes in the supplied buffer. Stop
  172.  * on end of file or end of line.  When FIOEOF is returned, there is a valid
  173.  * line of data without the normally implied \n.
  174.  */
  175. ffgetline(buf, nbuf, nbytes)
  176.     register char  *buf;
  177.     register int    nbuf;
  178.     register int   *nbytes;
  179. {
  180.     register int    c;
  181.     register int    i;
  182.  
  183.     i = 0;
  184.     while ((c = getch()) != EOF && (c & 0xFF) != '\n') {
  185.         buf[i++] = c;
  186.         if (i >= nbuf)
  187.             return FIOLONG;
  188.     }
  189.     if (c == EOF && (iostat == -1L)) {
  190.         ewprintf("File read error");
  191.         return FIOERR;
  192.     }
  193.     *nbytes = i;
  194.     return c == EOF ? FIOEOF : FIOSUC;
  195. }
  196.  
  197. #ifndef    NO_BACKUP
  198. #include "backup_suffix.h"
  199. /*
  200.  * Rename the current file into a backup copy, possibly after deleting the
  201.  * original file.
  202.  */
  203. fbackupfile(fname)
  204.     char           *fname;
  205. {
  206.     BPTR            twiddle, lock;
  207.     char            buffer[NFILEN];
  208.  
  209.     if (!fname)
  210.         return FALSE;
  211.     (void) strncpy(buffer, fname, NFILEN - 1);
  212.     (void) strcat(buffer, BACKUP_SUFFIX);
  213.  
  214.     lock = Lock(fname, (ULONG) EXCLUSIVE_LOCK);    /* does file exist?     */
  215.     if (!lock)
  216.         return (FALSE);    /* nope, return error     */
  217.  
  218.     twiddle = Lock(buffer, (ULONG) EXCLUSIVE_LOCK);
  219.     if (twiddle) {        /* delete old backup     */
  220.         UnLock(twiddle);/* let it go         */
  221.         if (!DeleteFile(buffer)) {
  222.             UnLock(lock);
  223.             return (FALSE);
  224.         }
  225.         twiddle = NULL;
  226.     }
  227.     /*
  228.      * rename file to backup name (after unlocking the file)
  229.      */
  230.     UnLock(lock);
  231.     return (int) Rename(fname, buffer);
  232. }
  233. #endif                /* NO_BACKUP */
  234.  
  235. #ifdef FOOB
  236. #define    DEFAULT_FOOB    (0L)
  237. FOOB
  238. getfoob(fname)
  239.     char           *fname;
  240. {
  241.     struct FileInfoBlock *fib;
  242.     BPTR            lock;
  243.     FOOB            out;
  244.  
  245.     if (fname == NULL)
  246.         return DEFAULT_FOOB;
  247.     if ((lock = Lock(fname, ACCESS_READ)) == NULL)    /* New file? */
  248.         return DEFAULT_FOOB;
  249.  
  250.     if ((fib = (struct FileInfoBlock *)
  251.          AllocMem(sizeof(struct FileInfoBlock), 0L)) == NULL) {
  252.         ewprintf("Couldn't get %d bytes", sizeof(struct FileInfoBlock));
  253.         UnLock(lock);
  254.         return DEFAULT_FOOB;
  255.     }
  256.     if (Examine(lock, fib))
  257.         out = fib->fib_Protection;
  258.     else {
  259.         ewprintf("Couldn't get protection bits for %s", fname);
  260.         out = DEFAULT_FOOB;
  261.     }
  262.  
  263.     UnLock(lock);
  264.     FreeMem(fib, sizeof(struct FileInfoBlock));
  265.     return out;
  266.  
  267. }
  268.  
  269. void
  270. putfoob(name, mask)
  271.     char           *name;
  272.     FOOB            mask;
  273. {
  274.     SetProtection(name, mask & ~FIBF_ARCHIVE);
  275. }
  276. #endif
  277.  
  278. #ifndef    NO_STARTUP
  279. /*
  280.  * Return name of user's startup file.  On Amiga, make it .mg in the current
  281.  * directory, then s:mg-startup
  282.  */
  283.  
  284. static char     startname[] = ".mg";
  285. static char     altstartname[] = "s:mg-startup";
  286.  
  287. char           *
  288. startupfile()
  289. {
  290.     BPTR            lock;
  291.  
  292.     if (lock = Lock(startname, (ULONG) SHARED_LOCK)) {
  293.         UnLock(lock);
  294.         return (startname);
  295.     }
  296.     if (lock = Lock(altstartname, (ULONG) SHARED_LOCK)) {    /* alternate */
  297.         UnLock(lock);
  298.         return (altstartname);
  299.     }
  300.     return (NULL);
  301. }
  302. #endif                /* NO_STARTUP */
  303.  
  304. /*
  305.  * The string "fn" is a file name. Perform any required name adjustments,
  306.  * including conversion to a fully qualified path if NO_DIR isn't defined.
  307.  */
  308.  
  309. extern char    *MyDirName;
  310.  
  311. char           *
  312. adjustname(fn)
  313.     register char  *fn;
  314. {
  315. #ifndef NO_DIR
  316.     static char     fnb[MAXPATH];
  317.     BPTR            lock;
  318.     unsigned long   PathName();
  319.     void            TackOn();
  320.     char           *dup, *p;
  321.  
  322.     if (!fn)
  323.         return fn;
  324.     if (!index(fn, ':')) {    /* no device         */
  325.         strcpy(fnb, MyDirName);
  326.         TackOn(fnb, fn);
  327.         if (!index(fn, '/'))    /* completely bare name */
  328.             return fnb;
  329.     } else
  330.         strcpy(fnb, fn);
  331.     /*
  332.      * Else fn has some path components in it.  We try to PathName the
  333.      * whole thing first, but since the file specified by fn may not
  334.      * exist, we PathName the leading part and TackOn the trailing part
  335.      * if it doesn't.
  336.      */
  337.     if (lock = Lock(fnb, SHARED_LOCK)) {
  338.         if (PathName(lock, fnb, (long) MAXPATH) != 0) {
  339.             UnLock(lock);
  340.             return fnb;
  341.         }
  342.         ewprintf("adjustname: PathName() failed!");
  343.         UnLock(lock);
  344.         return fn;
  345.     }
  346.     if (!(p = rindex(fnb, '/')))
  347.         p = index(fnb, ':');
  348.     p++;
  349.     strcpy((dup = malloc(strlen(p) + 1)), p);
  350.     *p = '\0';
  351.     if (lock = Lock(fnb, SHARED_LOCK)) {
  352.         if (PathName(lock, fnb, (long) MAXPATH) != 0) {
  353.             UnLock(lock);
  354.             TackOn(fnb, dup);
  355.             free(dup);
  356.             return fnb;
  357.         }
  358.         ewprintf("adjustname: PathName() failed!");
  359.         UnLock(lock);
  360.     }
  361.     free(dup);
  362. #endif
  363.     return fn;        /* if all else fails     */
  364. }
  365.  
  366. /*
  367.  * Functions to read/write into the I/O buffer
  368.  */
  369.  
  370. VOID 
  371. FlushBuf()
  372. {
  373.     if (niobuf > 0) {
  374.         iostat = Write(ffh, iobuf, (long) niobuf);
  375.         niobuf = 0;
  376.     }
  377. }
  378.  
  379. /*
  380.  * Fill up the input buffer and return the first character in it.
  381.  */
  382. int 
  383. FillBuf()
  384. {
  385.     if ((iostat = Read(ffh, iobuf, (long) NIOBUF)) <= 0L)
  386.         return (EOF);
  387.     ibufo = 0;
  388.     niobuf = (int) iostat;
  389.     return (int) (iobuf[ibufo++]);
  390. }
  391.  
  392. #ifndef NO_DIRED
  393.  
  394. #include "kbd.h"
  395.  
  396. copy(frname, toname)
  397.     char           *frname, *toname;
  398. {
  399. #ifdef    LATTICE
  400.     int             error;
  401.     struct ProcID   pid;
  402.     if (error = forkl("copy", "copy", frname, toname, NULL, NULL, &pid))
  403.         return error;
  404.     return (int) wait(&pid);
  405. #else    /* MANX (v3.6) or AZTEC (v5.0) */
  406.     return fexecl("copy", "copy", frname, toname, (char *) 0);
  407. #endif
  408. }
  409.  
  410. struct buffer  *
  411. dired_(dirname)
  412.     char           *dirname;
  413. {
  414.     register struct buffer *bp;
  415.     char            line[256];
  416.     struct buffer  *findbuffer();
  417.     char           *tmpname, *mktemp();
  418.     int             i;
  419.     VOID            lfree();
  420.  
  421.     if ((dirname = adjustname(dirname)) == NULL) {
  422.         ewprintf("Bad directory name");
  423.         return NULL;
  424.     }
  425.     if (!isdirectory(dirname)) {
  426.         ewprintf("Not a directory: %s", dirname);
  427.         return NULL;
  428.     }
  429.     if ((bp = findbuffer(dirname)) == NULL) {
  430.         ewprintf("Could not create buffer");
  431.         return NULL;
  432.     }
  433.     bclear(bp);        /* clear out leftover garbage     */
  434.     (void) strcpy(line, "list >");
  435.     (void) strncat(line, tmpname = mktemp("ram:mgXXX.XXX"), sizeof(line));
  436.     (void) strncat(line, " \"", sizeof(line));
  437.     (void) strncat(line, dirname, sizeof(line));
  438.     (void) strncat(line, "\"", sizeof(line));
  439.     Execute(line, 0L, 0L);
  440.     if (ffropen(tmpname) != FIOSUC) {
  441.         ewprintf("Can't open temporary dir file");
  442.         return NULL;
  443.     }
  444.     if (ffgetline(line, sizeof(line), &i) != FIOSUC ||
  445.         strncmp(line, "Directory", 9) != 0) {
  446.         ffclose();
  447.         DeleteFile(tmpname);
  448.         ewprintf("No such directory: `%s'", dirname);
  449.         return NULL;
  450.     }
  451.     line[0] = line[1] = ' ';
  452.     while (ffgetline(&line[2], sizeof(line) - 3, &i) == FIOSUC) {
  453.         line[i + 2] = '\0';
  454.         (VOID) addline(bp, line);
  455.     }
  456.     ffclose();
  457.     DeleteFile(tmpname);
  458.     bp->b_dotp = lforw(bp->b_linep);    /* go to first line */
  459.     (VOID) strncpy(bp->b_fname, dirname, NFILEN);
  460.     if ((bp->b_modes[0] = name_mode("dired")) == NULL) {
  461.         bp->b_modes[0] = &map_table[0];
  462.         ewprintf("Could not find mode dired");
  463.         return NULL;
  464.     }
  465.     bp->b_nmodes = 0;
  466.     return bp;
  467. }
  468.  
  469. #ifndef    MANX
  470. char           *
  471. mktemp(pattern)
  472.     char           *pattern;
  473. {
  474.     /* quick hack mktemp for this purpose only */
  475.     register char  *name, *printo;
  476.     register unsigned short counter = 0;
  477.  
  478.     if (!pattern)
  479.         return pattern;
  480.     if ((name = malloc(strlen(pattern) + 5)) == NULL)
  481.         panic("Manx sucks rocks!");
  482.     (VOID) strcpy(name, pattern);
  483.     printo = name + strlen(name);
  484.     do
  485.         (void) sprintf(printo, "%d", counter += 1);
  486.     while (counter > 0 && access(name, 0) == 0);
  487.     if (counter == 0)
  488.         panic("Manx _really_ sucks!");
  489.     return name;
  490. }
  491. #endif
  492.  
  493. #define LIST_LINE_LENGTH 58    /* Size of line from List */
  494.  
  495. int
  496. d_makename(lp, fn)
  497.     register struct line *lp;
  498.     register char  *fn;
  499. {
  500.     register char  *cp;
  501.     int             n = 2;
  502.  
  503.     if (!fn)
  504.         return 0;
  505.     if (llength(lp) < LIST_LINE_LENGTH)
  506.         return ABORT;
  507.     if (lgetc(lp, 2) == ':')
  508.         return ABORT;    /* FileNote line     */
  509.     (VOID) strcpy(fn, curbp->b_fname);
  510.     cp = fn + strlen(fn);
  511.     if ((cp[-1] != ':') && (cp[-1] != '/'))    /* append '/' if needed     */
  512.         *cp++ = '/';
  513.     while (lgetc(lp, n) != ' ') {
  514.         *cp++ = lgetc(lp, n);
  515.         n++;
  516.     }
  517.     *cp = '\0';
  518.     return strncmp(&lp->l_text[31], "Dir", 3) == 0;
  519. }
  520.  
  521. #ifndef    LATTICE
  522. static 
  523. isdirectory(name)
  524.     char           *name;
  525. {
  526.     long            lock;
  527.     struct FileInfoBlock *fib;
  528.     int             result;
  529.  
  530.     if ((lock = Lock(name, ACCESS_READ)) == NULL)
  531.         return FALSE;
  532.     if ((fib = (struct FileInfoBlock *)
  533.          AllocMem((long) sizeof(struct FileInfoBlock), MEMF_PUBLIC)) == NULL) {
  534.         UnLock(lock);
  535.         return FALSE;
  536.     }
  537.     result = (fib->fib_DirEntryType > 0L) ? TRUE : FALSE;
  538.     FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  539.     UnLock(lock);
  540.     return result;
  541. }
  542. #endif
  543.  
  544. #endif
  545.  
  546. #ifndef USE_ARP
  547.  
  548. /*
  549.  * Here are work-alikes for the few ARP commands now used by the Amiga
  550.  * version of mg.  These may go away if we require ARP in future.
  551.  */
  552.  
  553. #ifndef LATTICE
  554. /* Changed because sysdef.h defines stricmp to be Strcmp for non-Lattice
  555.  * compilers.  This function is required for MANX3.6 and MANX5.0.
  556.  */
  557. Strcmp(s1, s2)
  558.     register char  *s1, *s2;
  559. {
  560.     while (tolower(*s1) == tolower(*s2)) {
  561.         if (*s1 == '\0')
  562.             return 0;
  563.         s1++;
  564.         s2++;
  565.     }
  566.     return (tolower(*s1) < tolower(*s2) ? -1 : 1);
  567. }
  568. #endif
  569. /*
  570.  * This PathName function shamelessly stolen from the Matt Dillon Shell. It
  571.  * is a slight mod of that program's get_pwd routine, from comm1.c.
  572.  */
  573. unsigned long
  574. PathName(flock, pwdstr, n)
  575.     BPTR            flock;
  576.     char           *pwdstr;
  577.     long            n;
  578. {
  579.     char           *name;
  580.     int             err = 0;
  581.  
  582.     BPTR            lock, newlock;
  583.     struct FileInfoBlock *fib;
  584.     int             i, len, nentries;
  585.  
  586.     lock = DupLock(flock);
  587.     nentries = n / FCHARS;
  588.  
  589.     fib = (struct FileInfoBlock *) AllocMem((long) sizeof(struct FileInfoBlock),
  590.                         MEMF_PUBLIC);
  591.     pwdstr[i = n - 1] = '\0';
  592.  
  593.     while (lock) {
  594.         newlock = ParentDir(lock);
  595.         if (!Examine(lock, fib))
  596.             ++err;
  597.         name = fib->fib_FileName;
  598. #ifdef    V11            /* Actuall, covers V12 also, but */
  599.         if (*name == '\0')    /* HACK TO FIX RAM: DISK BUG */
  600.             name = "RAM";
  601. #endif
  602.         len = strlen(name);
  603.         if (newlock) {
  604.             if (i == n - 1) {
  605.                 i -= len;
  606.                 movmem(name, pwdstr + i, len);
  607.             } else {
  608.                 i -= len + 1;
  609.                 movmem(name, pwdstr + i, len);
  610.                 pwdstr[i + len] = '/';
  611.             }
  612.         } else {
  613.             i -= len + 1;
  614.             movmem(name, pwdstr + i, len);
  615.             pwdstr[i + len] = ':';
  616.         }
  617.         UnLock(lock);
  618.         lock = newlock;
  619.     }
  620.     FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  621.     movmem(pwdstr + i, pwdstr, n - i);
  622.     if (err)
  623.         return (0L);
  624.     return ((unsigned long) n - i - 1);
  625. }
  626.  
  627. static void
  628. TackOn(path, file)
  629.     char           *path, *file;
  630. {
  631.     if (*file != '\0') {
  632.         if (path[strlen(path) - 1] != ':')
  633.             strcat(path, "/");
  634.         strcat(path, file);
  635.     }
  636. }
  637. #endif
  638.